package com.zzyl.nursing.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.ai.AIModelInvoker;
import com.zzyl.nursing.domain.HealthAssessment;
import com.zzyl.nursing.dto.HealthAssessmentDto;
import com.zzyl.nursing.mapper.HealthAssessmentMapper;
import com.zzyl.nursing.service.IHealthAssessmentService;
import com.zzyl.nursing.vo.HealthReportVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 健康评估Service业务层处理
 *
 * @author mr.luo
 * @date 2025-05-22
 */
@Slf4j
@Service
public class HealthAssessmentServiceImpl extends ServiceImpl<HealthAssessmentMapper, HealthAssessment> implements IHealthAssessmentService {
    @Autowired
    private HealthAssessmentMapper healthAssessmentMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private AIModelInvoker aiModelInvoker;


    /**
     * 查询健康评估
     *
     * @param id 健康评估主键
     * @return 健康评估
     */
    @Override
    public HealthAssessment selectHealthAssessmentById(Long id) {
        return getById(id);
    }

    /**
     * 查询健康评估列表
     *
     * @param healthAssessment 健康评估
     * @return 健康评估
     */
    @Override
    public List<HealthAssessment> selectHealthAssessmentList(HealthAssessment healthAssessment) {
        return healthAssessmentMapper.selectHealthAssessmentList(healthAssessment);
    }


    /**
     * 修改健康评估
     *
     * @param healthAssessment 健康评估
     * @return 结果
     */
    @Override
    public int updateHealthAssessment(HealthAssessment healthAssessment) {
        return updateById(healthAssessment) ? 1 : 0;
    }

    /**
     * 批量删除健康评估
     *
     * @param ids 需要删除的健康评估主键
     * @return 结果
     */
    @Override
    public int deleteHealthAssessmentByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除健康评估信息
     *
     * @param id 健康评估主键
     * @return 结果
     */
    @Override
    public int deleteHealthAssessmentById(Long id) {
        return removeById(id) ? 1 : 0;
    }


    /**
     * 新增健康评估
     *
     * @param dto 健康评估
     * @return 结果
     */
    @Transactional
    @Override
    public Long insertHealthAssessment(HealthAssessmentDto dto) {
        //根据身份证号从缓存中提取体检报告内容
        String content = (String) redisTemplate.opsForHash().get(CacheConstants.NURSING_HEATHER_KEY, dto.getIdCard());
        if(StrUtil.isBlank(content)) {
            throw new BaseException("体检报告未上传");
        }

        //读取resources下的prompt.txt内容
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("prompt.txt");
        String promptTemplate = IoUtil.read(in, StandardCharsets.UTF_8);

        //组织prompt
        String prompt = promptTemplate.replace("prompt",content);

        //调用百度千帆接口，获取结果
        String result = aiModelInvoker.qianfanInvoker(prompt);
        log.info("[百度千帆]对话结果：{}", result);
        if(StrUtil.isBlank(result)) {
            throw new BaseException("调用百度千帆大模型失败");
        }


        //解析JSON结果，将数据存入健康评估表
        HealthReportVo healthReportVo = JSON.parseObject(result, HealthReportVo.class);
        long  id = saveHealthReportData(dto, healthReportVo);

        //删除redis中当前老人的体检报告内容
        redisTemplate.opsForHash().delete(CacheConstants.NURSING_HEATHER_KEY, dto.getIdCard());

        log.info("[健康评估]评估完成，ID：{}", id);
        return id;
    }

    /**
     * 保存健康评估数据
     * @param dto
     * @param vo
     * @return
     */
    private long saveHealthReportData(HealthAssessmentDto dto , HealthReportVo vo) {

        HealthAssessment assessment = new HealthAssessment();
        assessment.setElderName(dto.getElderName()); //老人姓名
        assessment.setIdCard(dto.getIdCard()); //老人身份证号
        assessment.setPhysicalExamInstitution(dto.getPhysicalExamInstitution()); //体检机构
        assessment.setPhysicalReportUrl(dto.getPhysicalReportUrl());//体检机构报告URL

        assessment.setBirthDate(IdcardUtil.getBirthDate(dto.getIdCard()).toLocalDateTime());//出生日期
        assessment.setAge(IdcardUtil.getAgeByIdCard(dto.getIdCard()));//年龄
        assessment.setGender(IdcardUtil.getGenderByIdCard(dto.getIdCard()));//性别

        double healthScore = vo.getHealthAssessment().getHealthIndex();
        assessment.setHealthScore(String.valueOf(healthScore));//健康评分
        assessment.setTotalCheckDate(vo.getTotalCheckDate());//总检日期
        assessment.setRiskLevel(vo.getHealthAssessment().getRiskLevel());//风险等级
        assessment.setReportSummary(vo.getSummarize());//报告总结
        assessment.setDiseaseRisk(JSON.toJSONString(vo.getRiskDistribution()));//疾病风险
        assessment.setAbnormalAnalysis(JSON.toJSONString(vo.getAbnormalData())); //异常分析
        assessment.setSystemScore(JSON.toJSONString(vo.getSystemScore()));//健康系统分值

        assessment.setSuggestionForAdmission(healthScore>=60 ? 0 : 1);//是否建议入住
        assessment.setNursingLevelName(getNursingLevelName(healthScore));//护理级别
        assessment.setAdmissionStatus(1);//未入住
        assessment.setAssessmentTime(LocalDateTime.now());//评估时间

        this.save(assessment);

        return assessment.getId();
    }

    private String getNursingLevelName(double healthScore) {
        if(healthScore<0 || healthScore>100){
            throw new BaseException("健康评分不在0-100之间");
        }

        String leveName = "正常";

        if(healthScore>=90) {
            leveName = "三级护理";
        } else if (healthScore>=80) {
            leveName = "二级护理";
        } else if (healthScore>=70) {
            leveName = "一级护理";
        } else if (healthScore>=60) {
            leveName = "特级护理";
        } else {
            leveName = "不建议入住";
        }

        return leveName;
    }

}
